package cn.com.surker.common;

import cn.com.surker.base.ExportInter;
import cn.com.surker.enums.StateEnum;
import cn.com.surker.excel.ExcelCell;
import cn.com.surker.excel.ExcelReportUtils;
import cn.com.surker.oauth.AuthUtils;
import cn.com.surker.redis.RedisUtils;
import cn.com.surker.spring.SpringContextHolder;
import cn.com.surker.system.entity.*;
import cn.com.surker.system.model.CacheUser;
import cn.com.surker.system.service.*;
import cn.com.surker.util.DateUtil;
import cn.com.surker.util.IpUtils;
import cn.com.surker.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public abstract class AbstractController {

	// protected Logger logger=LoggerFactory.getLogger("controller");


	@Value("${erp.org.id}")
	protected Long orgId;

	@Value("${erp.org.code}")
	protected String orgCode;

	@Value("${erp.datasource.erp.db}")
	protected String erpDb;

	@Value("${erp.datasource.ds.id}")
	protected Long dsId;

	@Value("${erp.datasource.org.name}")
	protected String orgName;

	@Value("${erp.datasource.org.fullname}")
	protected String orgFullName;

	//	泵送设备是否根据合同类型做区分
	protected static final boolean PUMP_ENABLE_QUALITY = false;
	@Resource
	protected RedisUtils redisUtils;

	@Resource
	protected MenuRoleControllerService menuRoleControllerService;
	@Resource
	protected RoleService roleService;
	@Resource
	protected UserService userService;
	@Resource
	private StationLogService logService;
	@Autowired
	private IErpOriginService erpOriginService;

	
	public HttpServletRequest getRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		return request;
	}

	public HttpServletResponse getResponse() {
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		return response;
	}
	/**
	 * 验证菜单的增删改权限
	 * @param url
	 * @return
	 */
	protected SysMenuRoleController isControlVerify(String url) {
		CacheUser cacheUser = getUser();
		SysMenuRoleController menuRoleController = menuRoleControllerService.findUidOrUrl(cacheUser.getId(), url);
		if (menuRoleController == null) {
			menuRoleController = new SysMenuRoleController();
			menuRoleController.setIsInsert(0);
			menuRoleController.setIsDelete(0);
			menuRoleController.setIsUpdate(0);
		}
		return menuRoleController;
	}
	/**
	 * 权限验证
	 * @param roleNameList
	 * @param args
	 * @return
	 */
	protected Integer isValidation(List<String> roleNameList, String... args) {
		Integer isFlag = 0;
		if (args == null || args.length == 0)
			return isFlag;
		if (roleNameList == null || roleNameList.size() == 0)
			return isFlag;
		for (int i = 0; i < args.length; i++) {
			if (roleNameList.contains(args[i]))
				return 1;
		}
		return isFlag;
	}
	/**
	 * 验证是否能访问
	 * @param url
	 * @return
	 */
	protected Boolean isVerify(String url) {
		CacheUser cacheUser = getUser();
		if (cacheUser == null)
			return false;

		if (cacheUser.getRoleList() == null || cacheUser.getRoleList().size() == 0)
			return false;

		if (!cacheUser.getRoleList().contains(url))
			return false;

		return true;
	}

	protected CacheUser getUser() {
		HttpServletRequest request = getRequest();
		String access_token = (String) request.getSession().getAttribute("erp_oauth_token");
		if (StringUtils.isNull(access_token)) {
			return RefreshUser();
		}

		if (redisUtils.exists(access_token))
			return (CacheUser) redisUtils.get(access_token);
		else
			return RefreshUser();
	}

	/**
	 * 使用本地cookie登录
	 * @return
	 */
	protected CacheUser RefreshUser() {
		/**cookie缓存KEY**/
		String secretKey = Constant.COOKIE_KEY;

		/**每次进入时判断session是否为空，为空则根据本地cookies登录**/
		String token = CookiesUtil.getCookies(getRequest(), secretKey);
		/**判断cookies中的值是否不为空**/
		if (!StringUtils.isNull(token)) {
			if (!StringUtils.isNull(AESCoder.decrypt(token, secretKey))) {
				/**如果token不为空则解析cookie信息**/
				JSONObject jsonObject = JSONObject.parseObject(AESCoder.decrypt(token, secretKey));
				if (!StringUtils.isNull(jsonObject.getString("token"))) {
					/**如果缓存用户存在**/
					String cacheToken = jsonObject.getString("token");
					if (redisUtils.exists(cacheToken)) {
						CacheUser cacheUser = (CacheUser) redisUtils.get(cacheToken);
						cacheUser.setRoleList(roleService.loadUserMenu(cacheUser.getId()));
						cacheUser.setRoleNameList(roleService.loadRoleName(cacheUser.getId()));
						redisUtils.set(cacheToken, cacheUser, 7200L);
						AbstractController.setUserCookie(cacheUser);
						return cacheUser;
					}
				}

				if (!StringUtils.isNull(jsonObject.getString("username"))
						&& !StringUtils.isNull(jsonObject.getString("password"))) {
					SysUser sysUser = new SysUser();
					sysUser.setUsername(jsonObject.getString("username"));
					sysUser.setPassword(jsonObject.getString("password"));
					sysUser.setStatus(StateEnum.ENABLED.getCode());

					/**如果数据库中账号信息和cookies值能匹配则自动登录**/
					SysUser user = userService.queryUser(sysUser.getUsername());
					if (user != null && user.getPassword().equals(sysUser.getPassword())) {
						CacheUser cacheUser = new CacheUser(user);
						cacheUser.setRoleList(roleService.loadUserMenu(user.getId()));
						cacheUser.setRoleNameList(roleService.loadRoleName(cacheUser.getId()));
						cacheUser.setIp(IpUtils.getIpAddress(getRequest()));
						cacheUser = logService.save(cacheUser);
						/**加密令牌**/
						String appToken = AuthUtils.createToken(cacheUser.getId() + new Date().getTime());
						cacheUser.setToken(appToken);
						redisUtils.set(appToken, cacheUser, 7200L);
						AbstractController.setUserCookie(cacheUser);
						return cacheUser;
					}
				} else {
					CookiesUtil.removeCookies(secretKey, getResponse());
				}
			}
		}
		return null;
	}

	/**
	 * 获取用户关联公司
	 * @return
	 */
	protected List<SysOrigin> getUserOrgList() {
		SysUser user =getUser();
		List<SysOrigin> orgList = erpOriginService.queryByUidOrigin(user.getId());
		return orgList;
	}

	/**
	 * 把用户加入到cookie和session中
	 *
	 * @param user
	 */
	public static void setUserCookie(CacheUser user) {
		/**cookie缓存KEY**/
		String secretKey = Constant.COOKIE_KEY;
		if (StringUtils.isNull(user.getToken())) {
			String appToken = AuthUtils.createToken(user.getId() + new Date().getTime());
			user.setToken(appToken);
		}
		/**将登录token存入session**/
		((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
				.getSession().setAttribute("erp_oauth_token", user.getToken());
		/**将用户信息存入cookie**/
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("username", user.getUsername());
		jsonObject.put("password", user.getPassword());
		jsonObject.put("token", user.getToken());
		if (!StringUtils.isNull(user.getOriginId()))
			jsonObject.put("originId", user.getOriginId());
		/**设置用户的cookies信息**/
		CookiesUtil.setCookies(secretKey, AESCoder.encrypt(jsonObject.toString(), secretKey),
				((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse());
	}

	protected DataSourceInfo getDataSource() {
		if (getUser() != null)
			if (getUser().getDataSourceInfo() != null)
				return getUser().getDataSourceInfo();

		return null;
	}

	protected String getAccess_token() {
		HttpServletRequest request = getRequest();
		String access_token = (String) request.getSession().getAttribute("erp_oauth_token");
		return access_token;
	}


	/**createToken
	 * 更新缓存用户
	 * @param user
	 */
	public static void updateCacheUser(String token, Object user){
		RedisUtils redisUtils = SpringContextHolder.getBean("redisUtils");
		redisUtils.set(token, user, 7200L);
	}

	protected void addReferer(){
		HttpServletRequest request= getRequest();
		String retUrl = request.getHeader("Referer");   
		request.getSession().setAttribute("redirectUrl", retUrl);;
	}


	/**
	 * 发送响应流方法
	 */
	public void setResponseHeader(HttpServletResponse response, String fileName) {
		try {
			try {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			response.setContentType("application/octet-stream;charset=ISO8859-1");
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			response.addHeader("Pargam", "no-cache");
			response.addHeader("Cache-Control", "no-cache");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 验证用户是否管理员
	 * @return
	 */
	public Boolean isAdmin(){
		CacheUser user = getUser();
		if(user == null){
			return false;
		}
		List<String> roleNameList = user.getRoleNameList();
		if (roleNameList.contains(Constant.SYS_ADMIN) || roleNameList.contains("软件工程师")
			|| roleNameList.contains("硬件工程师")) {
			return true;
		}
		return false;
	}

	/**
	 * 导出excel
	 *
	 * @param sheetName
	 * @param title
	 * @param dataList
	 * @param wb
	 * @return
	 */
	protected <T extends ExportInter> XSSFWorkbook exportTotalReport(String sheetName, String title, List<T> dataList, XSSFWorkbook wb) {
		if (dataList == null || dataList.isEmpty()) {
			//	没有数据
			return null;
		}
		//	获取所有的注解属性
		T t = dataList.get(0);
		Class<?> clazz = t.getClass();
		// 存储所有带有 ExcelCell 注解的字段
		List<Field> annotatedFields = new ArrayList<>();
		// 获取所有字段（包括父类字段）

		/*Field[] declaredFields = clazz.getDeclaredFields();
		for (Field field : declaredFields){
			ExcelCell annotation = field.getAnnotation(ExcelCell.class);
			if (annotation != null){
				annotatedFields.add(field);
			}
		}*/
		while (clazz != null) {
			for (Field field : clazz.getDeclaredFields()) {
				if (field.isAnnotationPresent(ExcelCell.class)) {
					annotatedFields.add(field);
				}
			}
			// 获取父类字段
			clazz = clazz.getSuperclass();
		}
		// 根据注解中的 sort 属性对字段进行排序
		// annotatedFields.sort(Comparator.comparingInt(field -> field.getAnnotation(ExcelCell.class).sort()));
		annotatedFields.sort(
			Comparator.comparingInt((Field field) -> field.getAnnotation(ExcelCell.class).sort())
				.thenComparingInt(field -> field.getAnnotation(ExcelCell.class).childSort())
		);
		// 获取列名并生成表头
		Object[] columns = new Object[annotatedFields.size()];
		//	属性表
		List<String> keyList = new ArrayList<>();
		//	需要合计的列
		List<String> totalKeyList = new ArrayList<>();
		for (int i = 0; i < annotatedFields.size(); i++) {
			Field field = annotatedFields.get(i);
			//	获取注解值
			ExcelCell annotation = field.getAnnotation(ExcelCell.class);
			columns[i] = annotation.value();  // 这里假设获取到注解的 header 字段
			//	获取字段值
			String fieldName = field.getName();
			keyList.add(fieldName);
			//	获取是否需要合并列
			boolean b = annotation.calcTotal();
			if (b) {
				//	需要合并
				totalKeyList.add(fieldName);
			}
		}
		//	生产excel的数据值
		List<Map<String, Object>> excelDataList = new ArrayList<>();
		for (int i = 0, s = dataList.size(); i < s; i++) {
			//	要排序,用linkmap
			Map<String, Object> excelData = new LinkedHashMap<>();
			T itemData = dataList.get(i);
			for (int a = 0, b = keyList.size(); a < b; a++) {
				String key = keyList.get(a);
				try {
					Object fieldValue = null;
					// 循环遍历类的继承层级，直到找到该字段
					for (Class<?> clazzItem = itemData.getClass(); clazzItem != null; clazzItem = clazzItem.getSuperclass()) {
						try {
							Field field = clazzItem.getDeclaredField(key);
							//	获取字段名
							String name = field.getName();
							//	拼接get方法
							String getMethod = "get" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
							//	反射取出get方法
							Method method = clazzItem.getMethod(getMethod);
							//	获取值
							fieldValue = method.invoke(itemData);
							if (fieldValue == null) {
								//	取出字段的默认值
								ExcelCell annotation = field.getAnnotation(ExcelCell.class);
								//	判定字段的类型
								Class<?> type = field.getType();
								if (Number.class.isAssignableFrom(type)) {
									double v = annotation.defaultNumValue();
									if (type == Integer.class) {
										fieldValue = (int) v; // 转换为int后自动装箱为Integer
									} else if (type == Long.class) {
										fieldValue = (long) v; // 转换为long后自动装箱为Long
									} else if (type == Float.class) {
										fieldValue = (float) v; // 转换为float后自动装箱为Float
									} else {
										// 处理其他Number子类
										fieldValue = v;
									}
								} else {
									String defaultValue = annotation.defaultStrValue();
									if (StringUtils.isNotBlank(defaultValue)) {
										fieldValue = defaultValue;
									}
								}
							} else if (fieldValue instanceof Date) {
								//	将日期数据转换为字符串
								ExcelCell annotation = field.getAnnotation(ExcelCell.class);
								String dateFormat = annotation.dateFormat();
								fieldValue = DateUtil.convertString((Date) fieldValue, dateFormat);
							}
							break;  // 找到字段后跳出循环
						} catch (NoSuchFieldException e) {
							// 如果当前类没有该字段，则继续查找父类
							continue;
						}
					}
					//	如果fiedlValue没有值,则表示没有查到值
					excelData.put(key, fieldValue);
				} catch (Exception e) {
					// 处理异常
					e.printStackTrace();
				}
			}
			// 添加到数据
			excelDataList.add(excelData);
		}
		XSSFWorkbook sheets = ExcelReportUtils.exportTotalReport(sheetName, title, columns, totalKeyList, excelDataList, wb);
		return sheets;
	}

}